import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Vector;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class OnlinePokerClient extends JApplet implements ActionListener,
		ChangeListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	Table t;
	Socket ClientSocket;
	public String nick = null;
	ObjectOutputStream oos = null;
	Message m = null;

	public boolean myTurn = false;
	int time = 0;

	JTextArea chatcontents = null;
	JTextField inputLine, raiseValue;
	JButton call, raise, fold, check;
	JLabel gameWait, timerLabel;
	JSlider slider;
	Image image1, image2;
	Timer timer;
	
	// The object we will use to write with instead of the standard screen graphics
    Graphics bufferGraphics;
    // The image that will contain everything that has been drawn on bufferGraphics.
    Image offscreen;
   
	public void init() {
		createGUI();
		// getContentPane().setBackground(Color.yellow);
		t = new Table(-1);
		try {
			ClientSocket = new Socket("127.0.0.1", 4500);
			Thread thread = new Thread(new OnlinePokerClientListener(
					ClientSocket, t, this));
			thread.start();
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		sendNick();
	}

	public void createGUI() {
				
		BackgroundPanel mainPanel = new BackgroundPanel();
		mainPanel.setLayout(new BorderLayout(0, 0));
		//setSize(1200, 690);//applet size.
		setContentPane(mainPanel);

		JPanel rightPanel = new JPanel();
		JPanel userActions = new JPanel();
		JPanel chatPanel = new JPanel();
		
		gameWait = new JLabel("Waiting for other players to join");
		gameWait.setAlignmentX(CENTER_ALIGNMENT);
		
		timerLabel = new JLabel();
		
		raise = new JButton("Raise");
		raise.addActionListener(this);
		
		call = new JButton("Call");
		call.addActionListener(this);
		
		fold = new JButton("Fold");
		fold.addActionListener(this);
		
		check = new JButton("Check");
		check.addActionListener(this);
		
		chatcontents = new JTextArea(18, 5);
		JScrollPane scrollPane = new JScrollPane(chatcontents);
		chatcontents.setEditable(false);
		chatcontents.setLineWrap(true);
		
		inputLine = new JTextField(15);
		raiseValue = new JTextField(5);		
		
		slider = new JSlider();
		slider.setMinimum(0);
		slider.addChangeListener(this);
		
		raiseValue.setPreferredSize(new Dimension(100, 20));
		raiseValue.setMaximumSize(new Dimension(100, 20));
		inputLine.addActionListener(this);
		
		rightPanel.setLayout(new GridLayout(2, 1));
		rightPanel.setBorder(BorderFactory.createTitledBorder("User Controls"));
		// UserActions.setLayout(new BoxLayout(UserActions,BoxLayout.Y_AXIS));
		// UserActions.setBorder(BorderFactory.createTitledBorder("User Actions"));
		userActions.setLayout(new FlowLayout());
		
		chatPanel.setLayout(new BoxLayout(chatPanel, BoxLayout.Y_AXIS));
		chatPanel.setBorder(BorderFactory.createTitledBorder("Chat"));
		chatPanel.add(scrollPane);
		chatPanel.add(inputLine);
		
		userActions.add(call);
		userActions.add(fold);
		userActions.add(check);
		userActions.add(raise);
		userActions.add(raiseValue);
		userActions.add(slider);
		mainPanel.add(userActions, BorderLayout.SOUTH);
		rightPanel.add(chatPanel);
		mainPanel.add(rightPanel, BorderLayout.EAST);
		mainPanel.add(gameWait, BorderLayout.CENTER);
		rightPanel.add(timerLabel);

		offscreen = createImage(getWidth(), getHeight());//Japplet - method
		bufferGraphics = offscreen.getGraphics();
		//mainPanel.setDoubleBuffered(true);

	}

	public void sendNick() {
		try {
			OutputStream out = ClientSocket.getOutputStream();

			nick = (String) JOptionPane.showInputDialog(getContentPane(),
					(String) "Type your Nick Name here");
			if (!nick.isEmpty()) {
				oos = new ObjectOutputStream(out);
				m = new Message("SendingNick", nick);
				oos.writeObject(m);
				oos.reset();
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void update(Graphics g) {
		paint(g);
	}

	public void actionPerformed(ActionEvent e) {
		if (myTurn) {
			if (e.getSource() == call) {
				myTurn = false;
				PlayerCalled();
				time = 0;
				timer.stop();
			}
			if (e.getSource() == raise) {
				int Value = Integer.parseInt(raiseValue.getText());
				myTurn = false;
				PlayerRaised(Value);
				time = 0;
				timer.stop();
			}
			if (e.getSource() == fold) {
				myTurn = false;
				PlayerFolded();
				time = 0;
				timer.stop();
			}
			if (e.getSource() == check) {
				myTurn = false;
				PlayerChecked();
				time = 0;
				timer.stop();
			}
		}
		if (e.getSource() == inputLine) {
			JTextField t = (JTextField) e.getSource();
			if (!t.getText().isEmpty()) {
				chatcontents.append(nick + ": " + t.getText() + "\n");
				m.MakeMessage("Chat", nick + ": " + t.getText() + "\n");
				try {
					oos.writeObject(m);
					oos.reset();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				t.setText("");
			}
		}

	}

	public void updateTable(Table temp) {
		System.out.println("Table Received");
		t = temp;
		if (chatcontents.getText().isEmpty()) {
			if (!t.ChManager.ChatData.isEmpty()) {
				chatcontents.append(t.ChManager.ChatData);
			}
		}
		repaint();
	}

	public void updateChatWindow(String text) {
		chatcontents.append(text);
	}

	public void stop() {

	}

	public void destroy() {
		System.out.println("Closed");
		m.MakeMessage("ClientClosing", null);
		try {
			oos.writeObject(m);
			oos.reset();
			oos.close();
			ClientSocket.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void PlayerFolded() {
		try {
			m.MakeMessage("PlayerFolded", null);
			oos.writeObject(m);
			oos.reset();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void PlayerChecked() {
		try {
			m.MakeMessage("PlayerChecked", null);
			oos.writeObject(m);
			oos.reset();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void PlayerRaised(int RaiseValue) {
		try {
			m.MakeMessage("PlayerRaised", RaiseValue);
			oos.writeObject(m);
			oos.reset();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public void PlayerCalled() {
		try {
			m.MakeMessage("PlayerCalled", null);
			oos.writeObject(m);
			oos.reset();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	class myTimerActionListener implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			time++;
			if (time == 1)
				repaint();
			// System.out.println(time % 20);
			timerLabel.setText("Your Turn: Timer = "
					+ Integer.toString(time % 20));
			if (time % 20 == 0) {
				m.MakeMessage("PlayerFolded", null);
				try {
					oos.writeObject(m);
					oos.reset();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				Timer t = (Timer) e.getSource();
				t.stop();
			}
		}
	}

	public void stateChanged(ChangeEvent e) {
		JSlider s = (JSlider) e.getSource();
		if (!s.getValueIsAdjusting()) {
			raiseValue.setText(Integer.toString(s.getValue()));
		}
	}

	public void startTimer() {
		// Set Slider Value
		slider.setMinimum(0);
		slider.setMaximum(t.PManager.getPlayer(nick).getCurrentWorth());
		timer = new Timer(1000, new myTimerActionListener());
		timer.setInitialDelay(500);
		timer.start();
		repaint();
	}

	public void DisplayWinnerInfo(Table temp) {
		t = temp;
		repaint();
		String Text = "";
		Iterator iter = t.tableWinners.iterator();
		while (iter.hasNext()) {
			Player player = (Player) iter.next();
			Text += "Nick = " + player.getName() + ", Current Worth = "
					+ Integer.toString(player.getCurrentWorth()) + "\n";
		}
		JOptionPane.showMessageDialog(null, "Winner(s): " + Text);
	}
	
	public void ReceivedTableList(String list)
	{
		//System.out.println(list);
		String temp = (String) JOptionPane.showInputDialog(getContentPane(),
				(String) "Enter TableNumber");
		try {
			oos.writeObject(new Message("ChosenTableNumber",temp));
			oos.reset();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

public void paint(Graphics g) {
		
		// Wipe off everything that has been drawn before
		// Otherwise previous drawings would also be displayed.
        bufferGraphics.clearRect(0,0,getWidth(),getHeight()); 
		
		super.paint(bufferGraphics);
		if (t.RManager.GameInProgress)
			gameWait.setVisible(false);

		int x = 5, y = 10;
		Vector<Player> players = new Vector<Player>();
		Player player;
		Card[] cardArray = new Card[2];
		players = t.PManager.getListOfPlayers();
		Iterator<Player> playersIter = players.iterator();

		bufferGraphics.setColor(Color.BLACK);
		bufferGraphics.drawString("Round: " + t.RManager.getRoundID(), x, y);
		bufferGraphics.drawString("Count of players: " + t.PManager.getCountofPlayers(), x,
				y + 15);
		bufferGraphics.drawString("Maximum players: " + t.MaximumPlayers, x, y + 30);
		bufferGraphics.drawString("Current High: " + t.RManager.getCurrHigh(), x, y + 45);
		y += 60;

		while (playersIter.hasNext()) {
			player = playersIter.next();
			cardArray = player.getCards();
			PlayerPosition playerPosition = player.getPlayerPosition();
			
			System.out.println(playerPosition.getXCor());
			
			//Drawing over the board
			bufferGraphics.drawString(player.getName(), playerPosition.getXCor()-16, playerPosition.yCor);
			bufferGraphics.drawString(player.getState(), playerPosition.getXCor()-16, playerPosition.yCor+13);
			//bufferGraphics.drawString(""+player.getCurrentWorth(), playerPosition.getXCor()-16, playerPosition.yCor+26);
			bufferGraphics.drawString(""+player.getBet(), playerPosition.getXCor()-16, playerPosition.yCor+26);
			
			if (player.getName().equals(nick)) {

				bufferGraphics.drawString("My Name: " + player.getName(), x, y);
				bufferGraphics.drawString("My State: " + player.getState(), x, y + 15);	
				
				try {
					image1 = ImageIO.read(new URL( getClass().getResource("cards/"), cardArray[0]
									.toString()+ ".gif"));
					image2 = ImageIO.read(new URL( getClass().getResource("cards/"), cardArray[1]
									.toString()+ ".gif"));
					bufferGraphics.drawImage(image1, 500, 515, 73, 97, this);
					bufferGraphics.drawImage(image2, 600, 515, 73, 97, this);
				} catch (Exception e) { /* handled in paintComponent() */
				}
				// bufferGraphics.drawString("My Cards: " + CardArray[0].toString() + "," +
				// CardArray[1].toString(), x, y + 30);
				bufferGraphics.drawString("My CurrentWorth/CurrentBet: "
						+ player.getCurrentWorth()+"/"+ player.getBet(), x, y + 45);
				y += 60;
			} else {
				//bufferGraphics.drawString("Other Player Name: " + player.getName(), x, y);
				//bufferGraphics.drawString("Other Player's Current Bet: " + player.getBet(), x, y + 15);				
			}
			y += 30;
		}
		Iterator<Card> it = t.cardsAtTable.iterator();
		bufferGraphics.drawString("Table Cards: ", x, y);
		y += 30;
		int XCoord = 350;
		while (it.hasNext()) {
			Card temp = it.next();
			try {
				Image tCard = javax.imageio.ImageIO.read(new java.net.URL(
						getClass().getResource("cards/"), temp.toString()
								+ ".gif"));
				bufferGraphics.drawImage(tCard, XCoord, 250, 73, 97, this);//community cards.
				XCoord += 100;

			} catch (MalformedURLException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			// bufferGraphics.drawString(temp.toString() + "|", x + 50, y);
			x += 75;
		}
		// draw the offscreen image to the screen like a normal image.
        // Since offscreen is the screen width we start at 0,0.
        g.drawImage(offscreen,0,0,this); 
	}
}